package com.geline.easyexcel.utils;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 解析动态查询SQL
 * 支持写法 [and user_name like '%${userName+}%']
 * 支持写法 [and status=#{status}]
 * 支持写法 [and id in(#{ids})] 默认id为字符类型
 * 支持写法 [and id in(#{ids:int})] 默认id为数字类型
 * @author: mengxin
 * @date: 2024/1/26 15:05
 */
public class DynamicSqlUtil {

    /**
     * 解析获取必填参数变量 ${key+} #{key+}
     * @param dynamicSql
     * @return [key1, key2]
     */
    public static List<String> parseRequiredKeyList(String dynamicSql){
        List<String> requiredKeys = ReUtil.findAllGroup0("\\{([^\\+]+)\\+\\}", dynamicSql);
        if(requiredKeys!=null && requiredKeys.size()>0){
            return requiredKeys.stream().map(row -> row.substring(1, row.length() - 2)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    //解析获取非必填参数变量 ${key} #{key}
    public static List<String> parseNormalKeyList(String dynamicSql){
        List<String> normalKeys = ReUtil.findAllGroup0("\\{([^\\}]+)\\}", dynamicSql);
        if(normalKeys!=null && normalKeys.size()>0){
            return normalKeys.stream().map(row -> row.substring(1, row.length() - 1)).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    public static List<String> parseAllKeyList(String dynamicSql){
        List<String> list = new ArrayList<>();
        List<String> requiredKeys = parseRequiredKeyList(dynamicSql);
        List<String> normalKeys = parseNormalKeyList(dynamicSql);
        list.addAll(requiredKeys);
        list.addAll(normalKeys);
        return list;
    }

    /**
     * 解析动态SQL+传入参数，生成新的可执行SQL
     * @param dynamicSql
     * @param map
     * @return
     */
    public static String parseSQL(String dynamicSql, Map<String, Object> map){
        //$xxx+表示检验必传参数
        List<String> requiredKeys = parseRequiredKeyList(dynamicSql);
        if(requiredKeys!=null && requiredKeys.size()>0){
            for(String key : requiredKeys){
                if(!map.containsKey(key)){
                    throw new RuntimeException(String.format("%s is required !", key));
                }
            }
        }
        String newSql = dynamicSql;
        for(String key : map.keySet()){
            Object value = map.get(key);
            if(!StrUtil.isBlankIfStr(value)){//value!=null && value!=''
                if(key.equals("ids")){
                    //[and id in(#{ids:int})]
                    newSql = newSql.replace("${ids:int}", String.valueOf(value));
                    newSql = newSql.replace("#{ids:int}", String.valueOf(value));
                    //[and id in(#{ids})]
                    String idList = StrUtil.join("','", Arrays.asList(String.valueOf(value).split(",")));
                    newSql = newSql.replace("${ids}", "'"+idList+"'");
                    newSql = newSql.replace("#{ids}", "'"+idList+"'");
                }else if(value instanceof CharSequence){
                    newSql = newSql.replace("${"+key+"+}", String.valueOf(value));
                    newSql = newSql.replace("${"+key+"}", String.valueOf(value));
                    newSql = newSql.replace("#{"+key+"+}", StringUtils.quotaMark(value));
                    newSql = newSql.replace("#{"+key+"}", StringUtils.quotaMark(value));
                }else {
                    newSql = newSql.replace("${"+key+"+}", String.valueOf(value));
                    newSql = newSql.replace("${"+key+"}", String.valueOf(value));
                    newSql = newSql.replace("#{"+key+"+}", String.valueOf(value));
                    newSql = newSql.replace("#{"+key+"}", String.valueOf(value));
                }
            }
        }

        //截取动态条件 [name=${name}]
        List<String> list = ReUtil.findAllGroup0("\\[([^\\]]+)\\]", newSql);
        if(list!=null && list.size()>0){
            for(String subStr : list){
                if(subStr.contains("${") || subStr.contains("#{")){
                    //清除有变量条件
                    newSql = newSql.replace(subStr, "");
                }else {
                    //去除条件的[]
                    newSql = newSql.replace(subStr, subStr.substring(1, subStr.length()-1));
                }
            }
        }
        //替换多个空格为一个空格
        newSql = newSql.replaceAll("\\s{2,}", " ");
        return newSql;
    }
}
